
import json
import os
import sys

sys.stdout.reconfigure(encoding='utf-8')

def toArray(s: list):
    if len(s) == 1 and len(s[0]) == 0:
        return ""
    return ",".join(map(lambda x: '"' + x.strip() + '"', s))


def genTrainer(infile):
    with open(infile, 'r', encoding='utf-8') as file:
        dataList = []
        for line in file:
            l = line.strip()
            if l.startswith('[') and len(l) > 2:
                dataList.append('"id" : "%s"' % l[1:l.rindex(']')])
                continue
            elif l.startswith('.items'):
                itemList = l[l.index('{') + 1:l.index('}')]
                dataList.append('"items" : [%s]' % toArray(itemList.split(',')))
            elif l.startswith('.trainerName'):
                dataList.append('"trainerName" : "%s"' % l[l.index('"') + 1:l.rindex('"')])
            elif l.startswith('.partySize') and l.find('(') != -1:
                dataList.append('"party":"%s"' % l[l.index('(') + 1:l.index(')')])

            elif l.startswith('.partyFlags'):
                name, value = l[0:-1].split('=')
                value = value.strip()
                if value == "0":
                    value = ['F_TRAINER_NONE']
                else:
                    value = value.split('|')
                dataList.append('"partyFlags":[%s]' % toArray(value))
            elif l.startswith('.party'):
                continue
            elif l.startswith(".encounterMusic_gender"):
                name, value = l[0:-1].split('=')
                value = value.strip()
                dataList.append('"encounterMusic_gender" : [%s]' % toArray(value.split('|')))
            elif l.startswith('.aiFlags'):
                name, value = l[0:-1].split('=')
                value = value.strip()
                if value == "0":
                    value = ['AI_SCRIPT_NONE']
                else:
                    value = value.split('|')
                dataList.append('"aiFlags" : [%s]' % toArray(value))
            elif l.startswith('.'):
                name, value = l[1:-1].split('=')
                dataList.append('"%s" : "%s"' % (name.strip(), value.strip()))
            elif l.startswith('}'):
                print('       ', ',\n        '.join(dataList))
                dataList.clear()
                print(line, end='')
            else:
                print(line, end='')


def genParty(infile):
    with open(infile, 'r', encoding='utf-8') as file:
        all_data = []
        party = {}
        for line in file:
            if line.startswith("static const struct "):
                data = {}
                data['id'] = line[line.index(' ', 22):line.index('[')].strip()
                party_array = []
                data['party'] = party_array
                all_data.append(data)
                continue
            line = line.strip()
            if line.startswith('.'):
                line = line[1:].replace(' ', '')
                if line.endswith(',') or line.endswith('}'):
                    line = line[:-1]
                k, v = line.split('=')
                if k == "moves":
                    v = v[1:]
                    v = v.split(',')
                elif k == 'iv' or k == 'lvl':
                    v = int(v)
                party[k] = v
                continue
            if line == '},' or line == '}':
                party_array.append(party)
                party = {}
                continue

        json.dump(all_data, fp=sys.stdout, indent='\t')


def array2c(a, default=""):
    if a is None or len(a) == 0:
        return default
    if type(a) == str:
        return a
    return "|".join(a)


def jsonTrainer(infile):
    with open(infile, 'r', encoding='utf-8') as file:
        data = json.load(file)
        print('const struct Trainer gTrainers[] = {')
        for d in data:
            print('\t[{0}] = {{'.format(d['id']))
            print('\t.partyFlags = {0},'.format(array2c(d.get('partyFlags'), default='0')))
            print('\t.trainerClass = {0},'.format(array2c(d.get('trainerClass'))))
            print('\t.encounterMusic_gender = {0},'.format(array2c(d.get('encounterMusic_gender'))))
            print('\t.trainerPic = {0},'.format(array2c(d.get('trainerPic'))))
            print('\t.trainerName = _("{0}"),'.format(array2c(d.get('trainerName'))))
            print('\t.items = {{{0}}},'.format(array2c(d.get('items'))))
            print('\t.doubleBattle = {0},'.format(array2c(d.get('doubleBattle'))))
            print('\t.aiFlags = {0},'.format(array2c(d.get('aiFlags'))))
            if d.get('party') is not None:
                print('\t.partySize = ARRAY_COUNT({0}),'.format(array2c(d.get('party'))))
                print('\t.party = {{.data={0}}},'.format(array2c(d.get('party'))))
            print("\t},")
        print("};")


def isNumberAndNot0(n):
    if n is None:
        return False
    if type(n) == str:
        n = int(n)
    if type(n) != int:
        return False
    if n == 0:
        return False
    return True


def jsonParty(infile):
    with open(infile, 'r', encoding='utf-8') as file:
        data = json.load(file)
        for d in data:
            have_item = False
            have_move = False
            for party in d['party']:
                if party.get('heldItem') is not None:
                    have_item = True
                moves = party.get("moves")
                if moves is not None and len(moves) != 0:
                    have_move = True
            if have_item and have_move:
                party_type = "TrainerMonItemCustomMoves"
            elif have_item:
                party_type = "TrainerMonItemDefaultMoves"
            elif have_move:
                party_type = "TrainerMonNoItemCustomMoves"
            else:
                party_type = "TrainerMonNoItemDefaultMoves"
            print('static const struct {1} {0}[] = {{'.format(d['id'], party_type))
            for party in d['party']:
                print('\t{')
                if isNumberAndNot0(party.get('iv')):
                    print('\t.iv = {0},'.format(party['iv']))
                if party.get('nature') is not None:
                    print('\t.nature = {0},'.format(party['nature']))
                if isNumberAndNot0(party.get('ability')):
                    print('\t.ability = {0},'.format(party['ability']))
                print('\t.lvl = {0},'.format(party['lvl']))
                if party.get('species') is not None:
                    print('\t.species = {0},'.format(party['species']))
                if party.get('heldItem') is not None:
                    print('\t.heldItem = {0},'.format(party['heldItem']))
                if moves is not None and len(moves) != 0:
                    print('\t.moves = {{{0}}},'.format(",".join(party['moves'])))
                if party.get('dFlag') is not None:
                    print('\t.dFlag = {0},'.format(party.get('dFlag')))
                print('\t},')
            print('};')


def __main__():
    func = sys.argv[1]
    infile = sys.argv[2]
    if func == 'j2p':
        jsonParty(infile)
    elif func == 'j2t':
        jsonTrainer(infile)
    elif func == 'p2j':
        genParty(infile)
    elif func == 't2j':
        genTrainer(infile)
    else:
        raise ValueError()


if __name__ == "__main__":
    __main__()
